#include "sys.h"


extern uint32 CreateSI();
//extern MsgList *Append_Msg_List(MsgList **,uint16 ,uint16 ,MMSG *);



void InitRngRspTLVTable()
{
	RngRsp_TLV_Table[1]  = L_05001_TA     ;
	RngRsp_TLV_Table[2]  = L_05002_PLA    ;
	RngRsp_TLV_Table[3]  = L_05003_OFA    ;
	RngRsp_TLV_Table[4]  = L_05004_RS     ;
	RngRsp_TLV_Table[5]  = L_05005_DFO    ;
	RngRsp_TLV_Table[6]  = L_05006_UCIDO  ;
	RngRsp_TLV_Table[7]  = L_05007_DOBP   ;
	RngRsp_TLV_Table[8]  = L_05008_MACADR ;
	RngRsp_TLV_Table[9]  = L_05009_BCID   ;
	RngRsp_TLV_Table[10] = L_05010_PMCID  ;
	RngRsp_TLV_Table[11] = L_05011_ABP    ;
	RngRsp_TLV_Table[12] = L_05012_FN     ;
	RngRsp_TLV_Table[13] = L_05013_IRON   ;
	RngRsp_TLV_Table[17] = L_05017_SLP   ;
	RngRsp_TLV_Table[18] = L_05018_GSCN  ;
	RngRsp_TLV_Table[20] = L_05020_RRF   ;
	RngRsp_TLV_Table[21] = L_05021_HPO   ;
	RngRsp_TLV_Table[150]= L_05150_RCA    ;
}
void InitRngReqTLVTable()
{
	RngReq_TLV_Table[1]  = L_04001_RDBP ;
	RngReq_TLV_Table[2]  = L_04002_SMA  ;
	RngReq_TLV_Table[3]  = L_04003_RA   ;
	RngReq_TLV_Table[4]  = L_04004_ABC  ;
	RngReq_TLV_Table[5]  = L_04005_SBID ;
	RngReq_TLV_Table[6]  = L_04006_RPI  ;
	RngReq_TLV_Table[7]  = L_04007_HOID ;
	RngReq_TLV_Table[8]  = L_04008_PDI  ;
	RngReq_TLV_Table[9]  = L_04009_PCID ;
	RngReq_TLV_Table[10] = L_04010_MHST ;
	RngReq_TLV_Table[11] = L_04011_EAT  ;
	RngReq_TLV_Table[12] = L_04012_RDRCL;
}



uint16 AccTLVBytes(Msg_TLV *TLV)
{
	uint16 length=0;
	Msg_TLV *tmp_p;
	tmp_p = TLV;
	do{
		length = (length + TLV->len);//indicate the value length
		length += 2; //including type and length bytes
		TLV = TLV->next;
	}while(TLV!=NULL);
	TLV = tmp_p;
	return length;
}

void SetRngRspTLVCodeRecv(Msg_TLV **rngrsp_tlv,uint32 rngRspStatus)
{
	switch(rngRspStatus)
	{
	case 3:
		AppendTLV(rngrsp_tlv, 1,RngRsp_TLV_Table,5);//time offset
		AppendTLV(rngrsp_tlv, 2,RngRsp_TLV_Table,10);//power offset
		AppendTLV(rngrsp_tlv, 3,RngRsp_TLV_Table,15);//frequency offset
		AppendTLV(rngrsp_tlv, 4,RngRsp_TLV_Table,rngRspStatus);//status
		AppendTLV(rngrsp_tlv, 150,RngRsp_TLV_Table,0);//ranging code attributes
		break;
	case 2:
		AppendTLV(rngrsp_tlv, 4,RngRsp_TLV_Table,rngRspStatus);//status
		break;
	case 1:
		AppendTLV(rngrsp_tlv, 4,RngRsp_TLV_Table,rngRspStatus);//status
		break;
	default:
		break;
	}
}

void SetRngRspTLVReqRecv(Msg_TLV **rngrsp_tlv ,uint32 rngRspStatus)
{
	uint32 usr=0;
	//critical section?
	switch(rngRspStatus)
	{
	case 3://success
		usr = CreateSI();
		AddCMT(&tableCMT,BASIC_CID,usr);
		AddCMT(&tableCMT,PRIMARY_CID,usr);
		AppendTLV(rngrsp_tlv, 4,RngRsp_TLV_Table,rngRspStatus);//status
		AppendTLV(rngrsp_tlv, 9,RngRsp_TLV_Table,tableMU2MI.usrAddr[usr]->cidGroup.BscCID);//basic cid
		AppendTLV(rngrsp_tlv,10,RngRsp_TLV_Table,tableMU2MI.usrAddr[usr]->cidGroup.PmyCID);//primary cid
		break;
	case 2://contunue
		AppendTLV(rngrsp_tlv, 1,RngRsp_TLV_Table,5);//time offset
		AppendTLV(rngrsp_tlv, 2,RngRsp_TLV_Table,10);//power offset
		AppendTLV(rngrsp_tlv, 3,RngRsp_TLV_Table,15);//frequency offset
		AppendTLV(rngrsp_tlv, 4,RngRsp_TLV_Table,rngRspStatus);//status
		break;
	case 1://abort
		AppendTLV(rngrsp_tlv, 4,RngRsp_TLV_Table,rngRspStatus);//status
		break;
	default:
		break;
	}
}


void SetRngReqTLVCdmaRecv(Msg_TLV **rngreq_tlv)
{
	AppendTLV(rngreq_tlv, 1,RngReq_TLV_Table,1); //requested downlink burst profile
	AppendTLV(rngreq_tlv, 2,RngReq_TLV_Table,1);//ss mac address
	AppendTLV(rngreq_tlv, 3,RngReq_TLV_Table,1);//mac version		
}


void SetMsgRngReq(MMSG **MMsg_pp)
{
	(*MMsg_pp)      =(MMSG *)malloc(sizeof(MMSG));
	(*MMsg_pp)->rngreq = (RNGREQ *)calloc(sizeof(RNGREQ),1);
	//Initail FCH Elements
	(*MMsg_pp)->rngreq->MMType = 0x4;	
	SetRngReqTLVCdmaRecv( &(*MMsg_pp)->rngreq->TLV);
	(*MMsg_pp)->rngreq->TLV_bytes = AccTLVBytes((*MMsg_pp)->rngreq->TLV);
}

void SetMsgRngRsp(MsgList **msglist,uint32 process)
{
	*msglist                 = (MsgList *)malloc(sizeof(MsgList));
	(*msglist)->mmsg         = (MMSG *)malloc(sizeof(MMSG));
	(*msglist)->mmsg->rngrsp = (RNGRSP *)calloc(sizeof(RNGRSP),1);
	//Initail FCH Elements
	(*msglist)->mmsg->rngrsp->MMType = 0x5;

	switch(process)
	{
	case TAG_RNGRSP_S1:
		(*msglist)->type = TYPE_RNGRSP;
		(*msglist)->CID  = 0xffff;
		SetRngRspTLVCodeRecv( &(*msglist)->mmsg->rngrsp->TLV,3);
		break;
	case TAG_RNGRSP_S2:
		(*msglist)->type = TYPE_RNGRSP;
		(*msglist)->CID  = 0xffff;
		SetRngRspTLVReqRecv( &(*msglist)->mmsg->rngrsp->TLV,3);
		break;
	default:
		break;
	}

	(*msglist)->mmsg->rngrsp->TLV_bytes = AccTLVBytes((*msglist)->mmsg->rngrsp->TLV);
}
void SetMsgCDMACode(MMSG **MMsg_pp,int isRNG )
{
	(*MMsg_pp)      =(MMSG *)malloc(sizeof(MMSG));
	(*MMsg_pp)->cdmacode = (CDMACODE *)calloc(sizeof(CDMACODE),1);
	//Initail FCH Elements
	(*MMsg_pp)->cdmacode->MMType = 255;
	if(isRNG)
	{
		(*MMsg_pp)->cdmacode->CDMACode = rand()%64;	
		(*MMsg_pp)->cdmacode->slots = rand()%5;
	}
	else
	{
		(*MMsg_pp)->cdmacode->CDMACode = rand()%64+128;	
		(*MMsg_pp)->cdmacode->slots = rand()%5+18;
	}
}

void FormRngReqTLV(MsgQ **MsgPtr,RNGREQ **rngreq)
{
	//Set the total bytes in TLV 
	Insert_MsgQ_DList(MsgPtr,(*rngreq)->TLV_bytes,8);
	while((*rngreq)->TLV!=NULL)
	{
		Insert_MsgQ_DList(MsgPtr,(*rngreq)->TLV->type,8);
		Insert_MsgQ_DList(MsgPtr,(*rngreq)->TLV->len,8);
		Insert_MsgQ_DList(MsgPtr,(*rngreq)->TLV->value,(uint8)(*rngreq)->TLV->len<<3);
		(*rngreq)->TLV = (*rngreq)->TLV->next;
	}
}
void FormRngRspTLV(MsgQ **MsgPtr,RNGRSP **rngrsp)
{
	//Set the total bytes in TLV 
	Insert_MsgQ_DList(MsgPtr,(*rngrsp)->TLV_bytes,8);
	while((*rngrsp)->TLV!=NULL)
	{
		Insert_MsgQ_DList(MsgPtr,(*rngrsp)->TLV->type,8);
		Insert_MsgQ_DList(MsgPtr,(*rngrsp)->TLV->len,8);
		Insert_MsgQ_DList(MsgPtr,(*rngrsp)->TLV->value,(uint8)(*rngrsp)->TLV->len<<3);
		(*rngrsp)->TLV = (*rngrsp)->TLV->next;
	}
	//free(*rngrsp);
}

void FormRngReq(MMSG **mmsg_pp,MsgQ **MsgPtr)
{
	Insert_MsgQ_DList(MsgPtr,(*mmsg_pp)->rngreq->MMType,8);
	FormRngReqTLV(MsgPtr,&(*mmsg_pp)->rngreq);
}

void FormRngRsp(MMSG **mmsg_pp,MsgQ **MsgPtr)
{
	Insert_MsgQ_DList(MsgPtr,(*mmsg_pp)->rngrsp->MMType,8);
	Insert_MsgQ_DList(MsgPtr,0,8);
	FormRngRspTLV(MsgPtr,&(*mmsg_pp)->rngrsp);
}
void DeFormRNGRSPTLV(BUFFER **buf_pp,RNGRSP **rngrsp)
{
	uint64 type = 0;
	uint64 len  = 0;
	uint64 tlv_bytes =0;
	uint64 value= 0;

	DeFormat2Val(buf_pp,&tlv_bytes,8);
	PrintMsgVal("RNGRSP","total tlv bytes",(uint32)tlv_bytes);
	(*rngrsp)->TLV_bytes = (uint16 )tlv_bytes;
	while(tlv_bytes!=0)
	{
		DeFormat2Val(buf_pp,&type,8);
		DeFormat2Val(buf_pp,&len ,8);
		DeFormat2Val(buf_pp,&value,(uint8)len*8);
		PrintMsgVal("RNGRSP","type",(uint32)type);
		PrintMsgVal("RNGRSP","length",(uint32)len);
		PrintMsgVal("RNGRSP","value",(uint32)value);
		AppendTLV(&(*rngrsp)->TLV, (uint16)type,RngRsp_TLV_Table,value);
		(tlv_bytes) -= (len+2); //including type length and value 
	}
}
void DeFormRNGRSP(BUFFER **buf_pp,RNGRSP **rngrsp)
{
	uint64 tmp;
	*rngrsp = (RNGRSP *)calloc(sizeof(RNGRSP),1);
	//DeFormat2Val(buf_pp,(uint64 *)&(*rngrsp)->MMType,L_MMTYPE_1);            
	DeFormat2Val(buf_pp,&tmp,8);
	PrintMsg("----------","Decode RNGRSP","----------");
	DeFormRNGRSPTLV(buf_pp,rngrsp);
}
void MgtRNGREQ(RNGREQ *rngreq)
{
	Msg_TLV *tlv = rngreq->TLV;
	while(tlv!=NULL)
	{
		switch(tlv->type)
		{
		case 1:
			break;
		case 2:
			break;
		case 3:
			break;
		default:
			break;
		}
		tlv = tlv->next;
	}

}

TMRT *Get_Timer()
{
	TMRT *p;
	p = (TMRT *)malloc(sizeof(TMRT));
	if(p == NULL)
	{
		printf("run out of memory");
		exit(1);
	}
	return(p);
}
void Append_Timer(TMRT **ptr,uint32 cid ,uint32 time)
{
	TMRT *newnode;
	TMRT *head;

	newnode = Get_Timer();
	newnode->cid=cid;
	newnode->time=time;
	newnode->next=NULL;
	head = *ptr;
	if(*ptr==NULL)
	{
		newnode->next=NULL;
		*ptr = newnode;
	}
	else
	{
		while((*ptr)->next!=NULL)
			*ptr=(*ptr)->next;
		(*ptr)->next=newnode;
		*ptr = head;
	}
}
TMRA *Get_TimerArray()
{
	TMRA *p;
	p = (TMRA *)malloc(sizeof(TMRA));
	if(p == NULL)
	{
		printf("run out of memory");
		exit(1);
	}
	return(p);
}
void Append_TimerArray(TMRA **ptr,uint32 cid,uint32 type ,uint32 time)
{
	TMRA *newnode;
	TMRA *head;

	newnode = Get_TimerArray();
	newnode->type=type;
	newnode->timer =NULL;
	newnode->next=NULL;
	Append_Timer(&newnode->timer,cid ,time);

	head = *ptr;
	if(*ptr==NULL)
	{
		newnode->next=NULL;
		*ptr = newnode;
	}
	else
	{
		while((*ptr)->next!=NULL)
			*ptr=(*ptr)->next;
		(*ptr)->next=newnode;
		*ptr = head;
	}
}

void InitTimerTable()
{
	int itimer=0;
	for(itimer=0;itimer<256;itimer++)
		TT[itimer]=0;

	TT[TIMER_T9] = TIMEOUT_T9;

}
void SETTime(uint32 cid,uint32 type)
{

	TMRA *ptr = timerAT;
	uint32 time = 0;
	time =  FRAMETIME*sysframe +TT[type];
	while(ptr != NULL)
	{
		if(ptr->type == type)
		{
			Append_Timer(&ptr->timer,cid ,time);
			return;
		}
		ptr = ptr->next;
	}
	Append_TimerArray(&timerAT,cid,type,time);

	//timerAT = ptr;
}


void RESETTimer(uint32 cid,uint32 type)
{
	TMRA *ptrtmra = timerAT;
	TMRT *ptrtmrt = NULL;
	while(ptrtmra!=NULL)
	{
		if(ptrtmra->type == type)
		{
			ptrtmrt = ptrtmra->timer;
			while(ptrtmrt != NULL)
			{
				if(ptrtmrt->cid == cid)
				{
					ptrtmrt->time = FRAMETIME*sysframe+TT[type];
					return;
				}
				ptrtmrt = ptrtmrt->next;
			}
		}
		ptrtmra = ptrtmra->next;
	}
	printf("ERROR\n");
	return ;
}
void STOPTimer(uint32 cid,uint32 type)
{
	TMRA *ptrtmra = timerAT;
	TMRT *ptrtmrtPrev = NULL;
	TMRT *ptrtmrt = NULL;

	while(ptrtmra!=NULL)
	{
		if(ptrtmra->type == type)
		{
			ptrtmrt = ptrtmra->timer;
			ptrtmrtPrev = ptrtmra->timer;
			while(ptrtmrt != NULL)
			{
				if(ptrtmrt->cid == cid)
				{
					if(ptrtmrtPrev == ptrtmrt)
						ptrtmra->timer = NULL;
					ptrtmrtPrev->next = ptrtmrt->next;
					free(ptrtmrt);
					return;
				}
				ptrtmrtPrev = ptrtmrt;
				ptrtmrt = ptrtmrt->next;
			}
		}

		ptrtmra = ptrtmra->next;
	}
	printf("ERROR\n");
	return ;
}
void SENDMSG(uint32 cid ,uint32 type)
{
	printf("Send Msg type = %d ,cid = %d \n",type,cid);
}
void ProcTimeOut()
{
	uint32 timeLimit = 0;
	TMRA *ptrA = NULL;
	TMRT *ptrT = NULL;
	ptrA = timerAT;
	timeLimit = (sysframe+10)*FRAMETIME;
	while(ptrA != NULL)
	{
		ptrT = ptrA->timer;
		while(ptrT != NULL)
		{
			if(ptrT->time < timeLimit)
				SENDMSG(ptrT->cid,ptrA->type);
			ptrT = ptrT->next;
		}
		ptrA = ptrA->next;
	}
}

MsgList * isCDMACodeCollision(MsgList *msglist ,MMSG *MMsg)
{
	//	MsgList *next = NULL;
	MsgList *now = NULL;
	//	MsgList *newMsglist =NULL;
	now = msglist;
	
	if(now == NULL)
	{
		msglist = Append_Msg_List(&msglist,255,0x0,MMsg);
		return msglist;
	}
	while(now->next != NULL)
	{

		if(now->mmsg->cdmacode->slots == MMsg->cdmacode->slots)
		{
			PrintMsgVal("CDMA Code","( Collision )",MMsg->cdmacode->CDMACode);
			InsertMsgList(&now,255,0x0,MMsg);
			now->mmsg->cdmacode->CDMACode |= 256;
			MMsg->cdmacode->CDMACode |= 256;
			return msglist;
		}
		else if(MMsg->cdmacode->slots > now->mmsg->cdmacode->slots && MMsg->cdmacode->slots < now->next->mmsg->cdmacode->slots)
		{
			InsertMsgList(&now,255,0x0,MMsg);
			return msglist;
		}
		now = now->next;
	}

	if(MMsg->cdmacode->slots > now->mmsg->cdmacode->slots)
		msglist = Append_Msg_List(&msglist,255,0x0,MMsg);
	else if(MMsg->cdmacode->slots < now->mmsg->cdmacode->slots)
	{//exchange
		msglist = Append_Msg_List(&msglist,255,0x0,msglist->mmsg);
		msglist->mmsg = MMsg;
	}
	else
	{
		InsertMsgList(&now,255,0x0,MMsg);
		now->mmsg->cdmacode->CDMACode |= 256;
		MMsg->cdmacode->CDMACode |= 256;
	}
	return msglist;
}
void DispatchCDMACode(MsgList *msglist)
{
	MsgList *tmpmsglist=NULL;

	while(msglist!=NULL)
	{
		if(msglist->mmsg->cdmacode->CDMACode<64)
		{
			tmpmsglist = msglist->next;
			msglist->next = NULL;
			//TO_NAME INITIAL RNG
		}
		else if(msglist->mmsg->cdmacode->CDMACode<128)
		{
			tmpmsglist = msglist->next;
			msglist->next = NULL;
			//TO_NAME PERIOD RNG 
		}
		else if(msglist->mmsg->cdmacode->CDMACode<192)
		{
			tmpmsglist = msglist->next;
			msglist->next = NULL;
			//TO_NAME BWA
		}
		else if(msglist->mmsg->cdmacode->CDMACode>256)
		{
			tmpmsglist = msglist->next;
			msglist->next = NULL;
			free(msglist->mmsg->cdmacode);
			free(msglist->mmsg);
			free(msglist);

		}
		else
		{
			printf("ERROR in CDMA CODE\n");
		}
		msglist = tmpmsglist;
	}

}
void ProcALLMMsgBS(MsgList *msglist,int *tag)
{
	PrintMsg("REQ Main","<< Start  >>","---------->");
	switch(msglist->type)
	{
	case TYPE_CDMACODE :
		if(msglist->mmsg->cdmacode->CDMACode<64)
			*tag = TAG_INITRNGCODE;
		else
			*tag = TAG_PERRNGCODE;
		PrintMsg("..........","Proc CDMA Code","..........");
		break;
	case 0 :
		break;
	default:
		break;
	}
	PrintMsg("REQ Main","<< Finish >>","<----------");
}
void ProcAllRSPMsg(MsgList **msglist,int tag)
{
//	int type =0;
	PrintMsg("RSP Main","<< Start  >>","---------->");
	switch(tag)
	{
	case TAG_RNGRSP_S1:
		SetMsgRngRsp(msglist,TAG_RNGRSP_S1);
		PrintMsg("..........","Set RNG RSP","..........");
		break;
	default:
		break;

	}
	PrintMsg("RSP Main","<< Finish >>","<----------");
}
void FromMsgQ2MsgList(MsgList *msglist,MsgQ *msgQ)
{

	BUFFER *buf = NULL;
	SDQ *dataQ =NULL ;
PrintMsg("FromMsgQ2MsgList","<< Start  >>","---------->");
	buf = FormatMsgQ2Buf(msgQ);
	free(msgQ);
	msgQ = NULL;

	dataQ = (SDQ *)malloc(sizeof(SDQ));
	dataQ->ptr = (uint32 *)buf->buffer;
	dataQ->length = buf->bitoffset;
	dataQ->next = dataQ->prev = dataQ;
	dataQ->status = 0 ;
	Append_MDQ(&sys.sysQ.bfSchSDUL,dataQ,dataQ->length,msglist->CID,0,0);

	//AddSMI(&sys.msg ,buf_p, (msglist)->type, (msglist)->CID);
	free((msglist)->mmsg);
	free(msglist);
	msglist = NULL;
PrintMsg("FromMsgQ2MsgList","<< Finish >>","<----------");
}
void FormatMsg2SysMsgQ(MsgList *msglist)
{
	MsgQ *msgQ = NULL;
	Init_MsgQ(&msgQ);
	switch(msglist->type)
	{

	case TYPE_RNGRSP:
		FormRngRsp(&(msglist->mmsg),&msgQ);
		break;

	default:
		break;
	}

	//it it for DL scheduler
	FromMsgQ2MsgList(msglist,msgQ);
}
MsgList* InitControlMMsg()
{
	MsgList *msglist = NULL;
	MMSG    *mmsg    = NULL;
	MsgList *tmp=NULL;
//	MsgQ *msgQ    = NULL;
	uint16 offset=0;
	int tag = 0;
	//int type =0;
	int i=0;
	InitRngRspTLVTable();
	InitRngReqTLVTable();
	for(i=0;i<10;i++)
	{
		SetMsgCDMACode(&mmsg,1);
		msglist = isCDMACodeCollision(msglist,mmsg);
		mmsg = NULL;
	}
	CollectMsgCDMAIE(msglist,&offset);
	tmp = msglist;

	while(tmp!=NULL)
	{

		tmp = tmp->next;
	}
	DispatchCDMACode(msglist);
	ProcALLMMsgBS(msglist,&tag);
	msglist = NULL;
	//msglist = (MsgList *)malloc(sizeof(MsgList));
	tag = TAG_RNGRSP_S1;
	ProcAllRSPMsg(&msglist,tag);
	FormatMsg2SysMsgQ(msglist);

	//SetTimer(0,0,1000);
	//SetTimer(1,0,1000);
	//SetTimer(0,1,1000);
	//SetTimer(1,1,1000);

	//StopTimer(1,1);
	//StopTimer(0,1);
	//SetTimer(0,1,100);
	return msglist;

	//ProcAllMMsgBS(msglist);
}